package com.cykj.faceledtv.netty;


import com.cykj.faceledtv.entity.LedAppTmpReadAndSkip;
import com.cykj.faceledtv.entity.NettyReceiverModel;
import com.orhanobut.logger.Logger;

import java.util.Arrays;
import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.ByteProcessor;

/**
 * tcp解码器
 *
 * @author jzh
 * @date 2018/11/06 14:14
 */
public class NettyDecode extends ByteToMessageDecoder {
    private boolean discarding;
    /**
     * 单包最大长度
     */
    private static final int maxLength = 512 * 1024;


    @Override
    protected final void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
        //查询出\r或者\n出现的长度
        LedAppTmpReadAndSkip tmpReadAndSkip = findEndOfLine(buffer);
        int eol = tmpReadAndSkip.getRead();
        if (!discarding) {
            if (eol >= 0) {
                //除去分隔符后的真实要读的数据，
                int length = eol - buffer.readerIndex();
                //要抛弃的字符串
                int delimLength = tmpReadAndSkip.getSkip();
                if (length > maxLength) {
                    buffer.readerIndex(eol + delimLength);
                }
                byte[] data = new byte[length];
                buffer.readBytes(data);
                buffer.skipBytes(delimLength);
                if (length < 1) {
                    return;
                }
                Logger.d("data=" + Arrays.toString(data));
                NettyReceiverModel model = new NettyReceiverModel();
                if (length == 1 && data[0] == 49) {
                    model.setIsHeart(true);
                } else {
                    model.setData(data);
                }
                out.add(model);
            } else {
                final int length = buffer.readableBytes();
                if (length > maxLength) {
                    buffer.readerIndex(buffer.writerIndex());
                    discarding = true;
                }
            }
        } else {
            if (eol >= 0) {
                buffer.readerIndex(eol + tmpReadAndSkip.getSkip());
                discarding = false;
            } else {
                buffer.readerIndex(buffer.writerIndex());
            }
        }
    }

    private LedAppTmpReadAndSkip findEndOfLine(final ByteBuf buffer) {
        LedAppTmpReadAndSkip tmpReadAndSkip = new LedAppTmpReadAndSkip();
        //找到第一个\r或者\n
        int i = buffer.forEachByte(ByteProcessor.FIND_CRLF);
        //后面跟着多个\n或者\r 处理多个\n\r的情况
        int skip = 1;
        for (int j = i + 1; j < buffer.readableBytes(); j++) {
            if (buffer.getByte(j) == '\r' || buffer.getByte(j) == '\n') {
                skip++;
            } else {
                break;
            }
        }
        tmpReadAndSkip.setRead(i);
        tmpReadAndSkip.setSkip(skip);
        return tmpReadAndSkip;
    }

}
